package com.jyf.redis.service.game.impl;

import com.jyf.redis.bean.game.Recorder;
import com.jyf.redis.common.model.ErrorCodeEnum;
import com.jyf.redis.common.model.Result;
import com.jyf.redis.manager.constant.NumGameConstant;
import com.jyf.redis.manager.utils.TimeUtils;
import com.jyf.redis.service.game.NumGameService;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 猜数字小游戏
 * 玩法：
 *   系统随机从0-9当中抽取【4】个数字，然后用户从0-9当中选择4个数字，如果用户猜的数字和系统生成的完全一样，则表示猜对了。
 * 规则：
 *   如果猜中的数字对了，就加圆，对一个数字加一个圆；
 *   如果猜中的数字和数字的位置都对，加三角形，数字和数字的位置都对一个，加一个三角形。
 *   若数字和数字的位置全对了，victory!!!
 * 提示：根据每次得到的圆形和三角形的数量，推断出本次猜中了那些数字和位置，最终一步步逼近正确答案！
 * 额外规则：
 *   猜的次数限制。
 *   时间限制。
 *
 */
@Service
public class NumGameServiceImpl implements NumGameService {


    private static final String original = "0123456789";




    private static final String numRegExp = "\\d{4}";
    private static final Pattern pattern = Pattern.compile(numRegExp);


    @Override
    public List<String> generateSysNm(int numCount) {
        Set<String> sysNum = new HashSet<>(numCount);
        for (;;) {
            char c = original.charAt(new Random().nextInt(original.length()));
            /*
            if(!list.contains(c)){
               list.add(c);
            }
            if(list.size() >= numCount){
               list -> str

               todo 可优化
            }

             */
            sysNum.add(String.valueOf(c));
            if (sysNum.size() >= numCount){
                return new ArrayList<>(sysNum);
            }
        }
    }

    public Result<List<String>> checkUserNumStr(int numCount,String userNumStr){
        Matcher matcher = pattern.matcher(userNumStr);
        if (!matcher.matches()){
            return Result.fail("必须为"+numCount+"数字!");
        }
        List<String> userNum = getUserNum(numCount, userNumStr);
        Set<String> set = new HashSet<>(userNum);
        if (set.size() < userNum.size()){
            return Result.fail("不能有重复数字!");
        }
        return Result.success(userNum);
    }

    @Override
    public Map<String, Integer> compareNum(List<String> sysNum, List<String> userNum) {
        /*
        传入两个字符串，
        if(str1.equals(str2)){
            return victory;
        }else{
            str -> list
            再比较
        }

        todo 可优化
         */



        Map<String,Integer> resultMap = new HashMap<>();
        resultMap.put(NumGameConstant.SQUARE,0);
        resultMap.put(NumGameConstant.CIRCLE,0);
        resultMap.put(NumGameConstant.VICTORY,0);

        for (int i = 0; i < userNum.size(); i++) {
            for (int j = 0; j < sysNum.size(); j++) {
                if (userNum.get(i).equals(sysNum.get(i))){
                    resultMap.put(NumGameConstant.SQUARE,resultMap.get(NumGameConstant.SQUARE) + 1);
                    resultMap.put(NumGameConstant.VICTORY,resultMap.get(NumGameConstant.VICTORY) + 1);
                }else {
                    if (sysNum.contains(userNum.get(i))){
                        resultMap.put(NumGameConstant.CIRCLE,resultMap.get(NumGameConstant.CIRCLE) + 1);
                    }
                }
                break;
            }
        }

        return resultMap;
    }

    @Override
    public Result handleResult(Map<String,Integer> map, HttpSession session, int numCount,String userNum,String time) {

        //可猜次数减一
        Integer guessCountLimit = (Integer)session.getAttribute(NumGameConstant.GUESS_COUNT_LIMIT);
        --guessCountLimit;
        session.setAttribute(NumGameConstant.GUESS_COUNT_LIMIT,guessCountLimit);

        //记录器
        List<Recorder> recorderList = (List<Recorder>)session.getAttribute(NumGameConstant.REPORTER);
        Recorder recorder = Recorder.builder()
                .times(recorderList.size() + 1)
                .square(map.get(NumGameConstant.SQUARE))
                .circle(map.get(NumGameConstant.CIRCLE))
                .victory(map.get(NumGameConstant.VICTORY))
                .time(time)
                .userNum(userNum)
                .build();
        recorderList.add(recorder);

        Map<String,Object> resultMap = new ConcurrentHashMap<>(2);
        if (map.get(NumGameConstant.VICTORY) == numCount){
            session.removeAttribute(NumGameConstant.SYS_NUM);
            //计算耗时
            Date startTime = (Date)session.getAttribute(NumGameConstant.START_TIME);
            Date endTime = new Date();
            long duration = TimeUtils.getDuration(startTime,endTime);

            //做记录、放排行榜(可设置一个最低入榜资格)

            resultMap.put("duration",duration);
            resultMap.put("recorder",recorder);
            resultMap.put("guessCountLimit",guessCountLimit);
            return Result.success("恭喜你回答正确!",resultMap);
        }else {
            //返回提示
            resultMap.put("recorder",recorder);
            resultMap.put("guessCountLimit",guessCountLimit);
            return Result.fail(ErrorCodeEnum.WRONG_ANSWER,"好好动动脑子!",resultMap);
        }
    }





    /**
     * 将用户输入的数字字符串转化成 集合
     * @param numCount 数字数量
     * @param userNumStr 用户输入的数字字符串
     * @return
     */
    private static List<String> getUserNum(int numCount,String userNumStr){
        List<String> userNum = new ArrayList<>(numCount);
        for (int i = 0; i < numCount; i++) {
            userNum.add(String.valueOf(userNumStr.charAt(i)));
        }
        return userNum;
    }

    /**
     * 生成能够重复的数字
     * @param numCount 数字数量
     * @return
     */
    private static List<String> getEnableRepeatSysNum(int numCount){
        String original = "0123456789";
        List<String> sysNum = new ArrayList<>(numCount);
        for (int i = 0; i < numCount; i++) {
            char c = original.charAt(new Random().nextInt(original.length()));
            sysNum.add(String.valueOf(c));
        }
        return sysNum;
    }


}